Skip to content

[Core] Add delete_thought tool and expose thought IDs in search/list#127

Closed
asherdiamant wants to merge 3 commits into
NateBJones-Projects:mainfrom
asherdiamant:add-delete-thought-tool
Closed

[Core] Add delete_thought tool and expose thought IDs in search/list#127
asherdiamant wants to merge 3 commits into
NateBJones-Projects:mainfrom
asherdiamant:add-delete-thought-tool

Conversation

@asherdiamant
Copy link
Copy Markdown

What this does

Adds a delete_thought tool to the core MCP server and surfaces thought IDs in search_thoughts and list_thoughts output so thoughts can be referenced for deletion.

Problem: Without a delete tool, stale or incorrect thoughts can only be superseded by capturing new "correction" entries, leading to clutter over time. There's no way to clean up the knowledge base from within an AI session.

Solution: Three small changes to server/index.ts:

  1. delete_thought tool — Accepts a thought UUID, confirms the thought exists, deletes it, and returns a preview of what was removed
  2. search_thoughts — Now includes ID: <uuid> in each result
  3. list_thoughts — Now includes [<uuid>] prefix in each result, and selects the id column

The match_thoughts RPC already returns the id column — this just surfaces it in the tool output.

What it requires

No new services or dependencies. Uses the existing thoughts table and Supabase client. The delete_thought tool requires service_role permissions (already used by all other tools).

Tested

Deployed and tested on a live Supabase instance with the standard Open Brain schema. Confirmed:

  • Deleting by valid ID returns confirmation with content preview
  • Deleting a non-existent ID returns an error message
  • IDs appear correctly in search and list output
  • Existing tools (capture, search, list, stats) are unaffected

@asherdiamant asherdiamant changed the title Add delete_thought tool and expose thought IDs in search/list [Core] Add delete_thought tool and expose thought IDs in search/list Mar 28, 2026
@matthallett1
Copy link
Copy Markdown
Collaborator

@claude review this PR

1 similar comment
@matthallett1
Copy link
Copy Markdown
Collaborator

@claude review this PR

@github-actions
Copy link
Copy Markdown

Claude Code is working…

I'll analyze this and get back to you.

View job run

@matthallett1
Copy link
Copy Markdown
Collaborator

@claude review this PR

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 30, 2026

Claude finished @matthallett1's task in 1m 56s —— View job


PR Review: [Core] Add delete_thought tool and expose thought IDs in search/list

  • Read CLAUDE.md and CONTRIBUTING.md for project context
  • Read the changed file (server/index.ts)
  • Review for alignment, safety, design patterns, and value
  • Post final review feedback

Summary: This PR adds a useful capability to OB1 — the ability to clean up stale or incorrect thoughts from within an AI session. The core idea is solid and the implementation is mostly clean, but there are a few issues worth addressing before merging.


What's Good

  • Alignment ✅ — Deleting thoughts is a natural hygiene operation for a persistent memory system. Without it, the only cleanup strategy is capturing "correction" entries, which creates clutter. This fills a real gap.
  • Scaffolding ✅ — Surfacing id in search_thoughts and list_thoughts is the right precondition for deletion. Users can't delete what they can't reference.
  • Fetch-before-delete ✅ — Confirming the thought exists and returning a preview of what was deleted is good UX. It prevents silent failures and gives the AI (and user) feedback on what was removed.
  • Pattern compliance ✅ — Remote Edge Function pattern maintained, no new dependencies, env vars used for credentials throughout.
  • Simplified capture flow — The refactor of capture_thought from a two-step upsert+update-embedding to a single parallel insert is architecturally cleaner.

Issues to Address

1. Undocumented capture_thought refactor (significant)

The PR description says "three small changes to server/index.ts" but the diff includes a fourth, larger change: capture_thought was refactored from the upsert_thought RPC to a direct insert. This isn't mentioned anywhere in the PR.

More importantly, this is a semantic regression: the previous upsert_thought RPC deduplicated thoughts on capture. The new insert creates duplicates freely. If the same content is captured twice, you'll get two identical rows. This may be intentional (the upsert behavior may have been unwanted), but it needs to be explicitly acknowledged and explained in the PR description.

Fix this →

2. Multi-tenant deletion scope (security)

The delete_thought tool uses the service_role key, which bypasses Row Level Security entirely. The .eq("id", id) filter is the only guard — there is no user_id scoping. In a single-user deployment this is fine, but in any shared/multi-user setup, any MCP client with MCP_ACCESS_KEY can delete any thought from any user in the database.

The existing tools have this same characteristic (list/search also don't filter by user), so this is a pre-existing pattern issue — but deletion is more destructive than reading. At minimum, a note in the tool description warning that this operates across the full database (not per-user) would help users make an informed choice about deployment.

3. No guard against mass deletion

A single bad call can permanently destroy data. There's no soft-delete, no recycle bin, and no confirmation step beyond the fetch-to-preview. The preview truncates at 100 characters, which may not be enough context for the AI to verify it's deleting the right thought (especially for short thoughts). Consider whether the full content (or at least more than 100 chars) should be shown before deletion, or at minimum whether the tool description should warn that this action is irreversible.

4. Minor: search_thoughts type annotation is incomplete

The type annotation in search_thoughts at line ~113 now includes id: string but the created_at field is present in the output (Captured: ...) but missing from the type object. This was a pre-existing issue, but the edit to add id is a good opportunity to clean it up.


Overall

The core feature is valuable and the implementation is correct. The two things that need resolution before merge:

  1. Acknowledge and explain the capture_thought upsert→insert change (or revert it if unintentional — it was not in the PR description and changes existing behavior)
  2. Add a note in the tool description about the global (non-user-scoped) deletion scope

The security concern about multi-tenant access is consistent with how the existing tools work, so it's not a blocker unique to this PR — but it's worth explicitly noting given that deletion is irreversible.

Copy link
Copy Markdown
Collaborator

@matthallett1 matthallett1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition — delete_thought fills a real gap and exposing IDs in search/list is the right prerequisite. Two things to address:

1. Scope the PR to what's advertised. The capture_thought refactor (two-step upsert → single parallel insert) is a separate change that isn't mentioned in the PR title or description. If you want to ship that optimization, please either:

  • Split it into its own PR with a clear description of what changed and why, OR
  • Revert the capture_thought changes in this PR and only ship delete_thought + ID exposure

2. Keep integrations/kubernetes-deployment/index.ts in sync. The k8s deployment still exposes the old 4-tool interface without delete_thought and without IDs in search/list results. After this PR, users on the self-hosted PostgreSQL deployment can't use the new delete workflow at all. Please add the same changes to the k8s server, or at minimum document the divergence in the PR description.

Happy to merge once these are addressed!

asherdiamant and others added 2 commits April 1, 2026 14:32
Without a delete tool, stale or incorrect thoughts can only be superseded
by capturing new "correction" entries, leading to clutter over time.

Changes:
- Add delete_thought tool (Tool 5) that deletes by UUID with confirmation
- Include thought IDs in search_thoughts output (ID: <uuid>)
- Include thought IDs in list_thoughts output ([<uuid>] prefix)
- The match_thoughts RPC already returns id; this surfaces it to the user

Tested on a live Supabase instance with the standard thoughts table schema.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add delete_thought tool to kubernetes-deployment/index.ts
- Add id field to search_thoughts and list_thoughts in k8s deployment
- Update delete_thought description: irreversible warning + single-user scope note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@asherdiamant asherdiamant force-pushed the add-delete-thought-tool branch from 7c80a49 to ed29eda Compare April 1, 2026 18:34
@asherdiamant
Copy link
Copy Markdown
Author

asherdiamant commented Apr 1, 2026

Rebased onto main branch which advanced in the meantime

@alanshurafa
Copy link
Copy Markdown
Collaborator

Both review items from @matthallett1 have been addressed in commit ed29eda:

  1. Scope: The capture_thought refactor has been removed. The current diff only contains delete_thought + ID exposure in search/list — nothing out of scope.
  2. K8s sync: integrations/kubernetes-deployment/index.ts now includes all three changes (delete_thought tool, IDs in search_thoughts, IDs in list_thoughts).

Ready for re-review.

@asherdiamant
Copy link
Copy Markdown
Author

asherdiamant commented Apr 9, 2026

Can anyone review this? @matthallett1? It seems stuck in the process. I just brought it up to date with the main branch so it's ready.

@asherdiamant
Copy link
Copy Markdown
Author

By the way, after updating the branch, I received this error:

Invalid workflow file: .github/workflows/ob1-gate.yml#L1
(Line: 52, Col: 14): Exceeded max expression length 21000

@justfinethanku
Copy link
Copy Markdown
Collaborator

Thanks for putting this together. I’m going to close this PR because it isn’t suitable for OB1 as a community PR.

This introduces a destructive core MCP tool by editing server/index.ts, and OB1 treats core MCP server changes as upstream infrastructure rather than mergeable community contribution surface area. The current PR also mixes core runtime changes with an integration file, so the boundary is off even before the feature risk is considered.

If this is something we want upstream, it needs a separate product/design decision first.

@asherdiamant
Copy link
Copy Markdown
Author

Thanks for putting this together. I’m going to close this PR because it isn’t suitable for OB1 as a community PR.

This introduces a destructive core MCP tool by editing server/index.ts, and OB1 treats core MCP server changes as upstream infrastructure rather than mergeable community contribution surface area. The current PR also mixes core runtime changes with an integration file, so the boundary is off even before the feature risk is considered.

If this is something we want upstream, it needs a separate product/design decision first.

@justfinethanku
I'm confused.
Matt's initial response to the PR was:
"Great addition — delete_thought fills a real gap and exposing IDs in search/list is the right prerequisite. ...
Happy to merge once these are addressed!"
Which I did. The addition of the integration change was to keep everything consistent at his request.

So I am not sure what changed.

How can we prevent chaff and noise accumulation in OB1 otherwise? Is there another solution? I came up with it due to necessity, I'm sure others need it too. I don't need this specific change, but the need for the tool is real.

@justfinethanku
Copy link
Copy Markdown
Collaborator

I think my agent framed it poorly. Sorry about that.

This should not have been closed, and when I get back to the office, I will re-open it.

But I do think it's important to make destructive actions less accessible. Depreciating and versioning in a database should be the priority, not deletion.

@asherdiamant
Copy link
Copy Markdown
Author

asherdiamant commented Apr 15, 2026

@justfinethanku
I understand the concern, and will add a solution when you reopen the PR. I suggest adding a table for deleted thoughts, where they can be recovered from, and it can be purged after a certain period, or manually, at the user's discretion. I prefer that to adding a flag into the main table, but that's another possible solution, since it keeps the live thoughts table focused and minimal. But that is another possible solution.

@alanshurafa
Copy link
Copy Markdown
Collaborator

Agreed that the ability to delete thoughts is an absolute necessity over time especially as the brain grows. Also agree that adding a "recycle bin is a great idea". Its common to have a retention policy for projects like this.

alanshurafa added a commit to alanshurafa/OB1 that referenced this pull request Apr 18, 2026
…release

Removes the delete_thought tool registration, the README table row,
and the 14 -> 13 tool count everywhere (README intro, Expected
Outcome, Tool Surface Area, metadata.json description). Renumbers
the remaining section comments in index.ts.

Adds an "Intentionally Excluded From This Release" section to the
README explaining why delete_thought will ship in a follow-up:
hard DELETE has no tombstone path on the enhanced-thoughts schema
today, and the maintainer's PR NateBJones-Projects#127 guidance was "depreciate and
version rather than delete." Shipping a safe soft-delete requires a
`deleted_at` column and a restore_thought sibling that don't exist
yet.

Why: the drafted implementation was hard DELETE on a row with no
deleted_at column, no audit trail, no restore path. Aligning with
PR NateBJones-Projects#127 posture is cheaper than trying to bolt on soft-delete here
without schema support — we'll land both tool and schema changes
together in a later PR.
alanshurafa added a commit to alanshurafa/OB1 that referenced this pull request May 20, 2026
…release

Removes the delete_thought tool registration, the README table row,
and the 14 -> 13 tool count everywhere (README intro, Expected
Outcome, Tool Surface Area, metadata.json description). Renumbers
the remaining section comments in index.ts.

Adds an "Intentionally Excluded From This Release" section to the
README explaining why delete_thought will ship in a follow-up:
hard DELETE has no tombstone path on the enhanced-thoughts schema
today, and the maintainer's PR NateBJones-Projects#127 guidance was "depreciate and
version rather than delete." Shipping a safe soft-delete requires a
`deleted_at` column and a restore_thought sibling that don't exist
yet.

Why: the drafted implementation was hard DELETE on a row with no
deleted_at column, no audit trail, no restore path. Aligning with
PR NateBJones-Projects#127 posture is cheaper than trying to bolt on soft-delete here
without schema support — we'll land both tool and schema changes
together in a later PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration Contribution: MCP extension or capture source

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants